<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>正在游戏中</title>
    <style>
        body {
            margin: 0px;
            background-color: #000000;
            overflow: hidden;
        }
    </style>
</head>

<script src="lib/three.js"></script>
<script src="lib/A_Star.js"></script>

<script src="lib/gl-matrix.js"></script>
<script src="lib/pako.js"></script>
<script src="dist/LOLLoader.js"></script>

<body oncontextmenu=self.event.returnValue=false onselectstart="return false">

</body>

<script>
    let camera, scene, renderer, fps;
    let plane;
    let hero = {
        mesh: null,
        pathSet: [],
        isMoving: false,
        speed: 1/60,
        heroModel: {},
    };
    let cameraMoving = {
        enable: false,
        dir: new THREE.Vector3(0,0,0),
    };

    let walls = [];
    for(let x=-200; x<=200; x++){
        walls.push(x, 50);
        walls.push(x, -50);
    }
    for(let z=-49; z<=49; z++){
        walls.push(-200, z);
        walls.push(200, z);
    }

    for(let i=0; i<500; i++){
        let x = Math.round(Math.random()*400-200);
        let z = Math.round(Math.random()*100-50);
        walls.push(x,z-2);
        walls.push(x,z-1);
        walls.push(x,z);
        walls.push(x,z+1);
        walls.push(x,z+2);

        x = Math.round(Math.random()*400-200);
        z = Math.round(Math.random()*100-50);
        walls.push(x-2,z);
        walls.push(x-1,z);
        walls.push(x,z);
        walls.push(x+1,z);
        walls.push(x+2,z);
    }

    let task = new AStar.Task();
    task.setWallFromArray(walls);

    init();
    animate();

    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
    }

    function setTarget(){
        let target = new THREE.Vector3(camera.position.x,0,camera.position.z-10);
        camera.lookAt(target);
    }

    const times = []; // 存储当前的时间数组
    function refreshLoop() {
        window.requestAnimationFrame(() => {
            const now = performance.now(); // 使用performance.now()能获取更高的精度
            while (times.length > 0 && times[0] <= now - 1000) {
                times.shift(); // 去掉1秒外的时间
            }
            times.push(now);
            fps = times.length;
            refreshLoop();
        });
    }
    refreshLoop();

    let unitZ = new THREE.Vector3(0,0,1);
    function animate() {
        hero.heroModel.fps = fps;
        if(cameraMoving.enable){
            camera.position.addScaledVector(cameraMoving.dir, 0.1);
            setTarget();
        }

        if(hero.isMoving){

            if(hero.pathSet.length>0){

                let next = hero.pathSet[0];
                let nextV3 = new THREE.Vector3(next.x, 0, next.y);
                if(hero.mesh.position.distanceTo(nextV3)<hero.speed){
                    hero.pathSet.shift();
                }else{
                    let dir = new THREE.Vector3().subVectors(nextV3, hero.mesh.position).normalize();
                    hero.mesh.position.addScaledVector(dir, hero.speed);
                    let angle = dir.angleTo(unitZ);
                    let nV3 = new THREE.Vector3().crossVectors(dir, unitZ);
                    if(nV3.y>0){
                        angle = -angle;
                    }

                    let rotateAngle;
                    let angleMin = 0.05;
                    let angleStep = 0.05;
                    let oldRotationY = hero.mesh.rotation.y;
                    if(angle>oldRotationY){
                        rotateAngle = angleStep;
                    }else{
                        rotateAngle = -angleStep;
                    }
                    if(Math.abs(angle-oldRotationY)>angleMin){
                        hero.mesh.rotation.set(0, oldRotationY+rotateAngle, 0);
                    }

                }

            }else{
                if(hero.heroModel.playAnimation){
                    hero.heroModel.playAnimation('idle1', 1000, 2730);
                }
                hero.isMoving = false;
            }

        }

        requestAnimationFrame( animate );
        renderer.render( scene, camera );
    }

    function initWall() {
        let standardMaterial = new THREE.MeshStandardMaterial( { color: new THREE.Color( 1, 1, 1 ) } );
        let wallGeometry = new THREE.BoxGeometry(1, 3, 1);
        wallGeometry.translate(0,1.5,0);
        let wall = new THREE.Mesh(wallGeometry, standardMaterial);

        for(let i=0; i<walls.length; i+=2){
            let oneWall = wall.clone();
            oneWall.position.set(walls[i],0,walls[i+1]);
            scene.add(oneWall);
        }
    }

    function init() {
        // 创建场景，所有的对象 相机 光源等对象都将放在这个场景上
        scene = new THREE.Scene();

        // 创建一个相机，它决定我们的视角
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.x = -180;
        camera.position.y = 30;
        camera.position.z = 10;
        setTarget();

        // 创建一个渲染器并设置宽高
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;

        renderer.setPixelRatio( window.devicePixelRatio );
        document.body.appendChild( renderer.domElement );
        window.addEventListener( 'resize', onWindowResize, false );

        //创建一个水平面
        let planeGeometry = new THREE.PlaneGeometry(400, 100);
        let textureLoader = new THREE.TextureLoader();
        let floorMap = textureLoader.load('./texture/floor.jpg');
        floorMap.wrapS = floorMap.wrapT = THREE.RepeatWrapping;
        floorMap.repeat.set(40,10);
        let planeMaterial = new THREE.MeshBasicMaterial({map: floorMap});
        plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        scene.add(plane);

        //创建一个英雄
        let url = ['./model/gailun/86_0.lanim', './model/gailun/86_0.lmesh', './model/gailun/garen_base_tx_cm.png'];
        let lolLoader = new LOLLoader();
        lolLoader.load(url).then((model) => {
            hero.heroModel = model;
            hero.heroModel.playAnimation('idle1', 1000, 2730);
            let mesh = model.mesh;
            let scale = 0.02;
            mesh.scale.set(scale,scale,scale);
            mesh.position.set(-180,0,0);
            hero.mesh = mesh;
            scene.add(mesh);

            let nameCanvas = document.createElement('canvas');
            nameCanvas.width = 128;
            nameCanvas.height = 128;
            let nameCtx = nameCanvas.getContext('2d');
            nameCtx.fillText('电车痴汉盖伦', 32, 40);
            let nameMap = new THREE.CanvasTexture(nameCanvas);
            nameMap.magFilter = THREE.NearestFilter;
            nameMap.minFilter = THREE.NearestFilter;
            let nameMaterial = new THREE.SpriteMaterial({
                map: nameMap,
                depthTest: false,
            });
            let nameSprite = new THREE.Sprite(nameMaterial);
            nameSprite.position.set(0,5.5/0.02,0);
            nameSprite.scale.set(5/0.02,5/0.02,5/0.02);
            hero.mesh.add(nameSprite);

            let hpCanvas = document.createElement('canvas');
            hpCanvas.width = 128;
            hpCanvas.height = 128;
            let hpCtx = hpCanvas.getContext('2d');
            hpCtx.strokeStyle = '#000000';
            hpCtx.strokeRect(32,50, 70, 10);
            hpCtx.fillStyle = '#00ff00';
            hpCtx.fillRect(32,50, 60, 10);
            let hpMap = new THREE.CanvasTexture(hpCanvas);
            let hpMaterial = new THREE.SpriteMaterial({
                map: hpMap,
                depthTest: false,
            });
            let hpSprite = new THREE.Sprite(hpMaterial);
            hpSprite.position.set(0,5.5/0.02,0);
            hpSprite.scale.set(5/0.02,5/0.02,5/0.02);
            hero.mesh.add(hpSprite);
        });

        let dlight = new THREE.DirectionalLight( 0xFFFFFF, 1 );
        dlight.position.set( 10, 10, 10 );
        dlight.target.position.set(0,0,0);
        scene.add( dlight );

        let alight = new THREE.AmbientLight( 0x404040 );
        scene.add( alight );

        initWall();

        renderer.domElement.addEventListener('mousemove', function (e) {
            let x = e.offsetX;
            let y = e.offsetY;

            let rect = renderer.domElement.getBoundingClientRect();
            let width = rect.width;
            let height = rect.height;

            let centerX = width/2;
            let centerY = height/2;


            if(x<100 || x>width-100 || y<100 || y>height-100){
                cameraMoving.enable = true;
                let dir = new THREE.Vector3(x-centerX, 0, y-centerY).normalize();
                cameraMoving.dir = dir;
            }else{
                cameraMoving.enable = false;
            }
        });

        renderer.domElement.addEventListener('mousedown', function (e) {
            if(e.button === 2){
                //右键
                let x = e.offsetX;
                let y = e.offsetY;

                let rect = renderer.domElement.getBoundingClientRect();
                let width = rect.width;
                let height = rect.height;

                let raycaster = new THREE.Raycaster();
                let mouse = new THREE.Vector2();
                mouse.x = ( x / width ) * 2 - 1;
                mouse.y = - ( y / height ) * 2 + 1;
                // 通过摄像机和鼠标位置更新射线
                raycaster.setFromCamera( mouse, camera );

                // 计算物体和射线的焦点
                let intersects = raycaster.intersectObject( plane );
                if(intersects.length>0){
                    let intersect = intersects[0];
                    let point = intersect.point;

                    let x = Math.round(point.x);
                    let y = Math.round(point.z);
                    task.setEnd(x,y);

                    let x1 = Math.round(hero.mesh.position.x);
                    let y1 = Math.round(hero.mesh.position.z);
                    task.setStart(x1,y1);

                    task.findPath();
                    hero.pathSet = task.pathSet.slice(0);
                    hero.isMoving = true;

                    hero.heroModel.playAnimation('run');

                }
            }
        })

    }

    function locateToHero(){
        let pos = hero.mesh.position;
        camera.position.set(pos.x, camera.position.y, pos.z+10);
        camera.lookAt(pos);
    }


    document.addEventListener('keydown', function (e) {
        if(e.keyCode === 32){
            //空格
            locateToHero();
        }
    });
</script>

</html>